<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //  属性监听-数据拦截--响应式的原理
        // vue2和vue3 响应式的区别
        /*
            vue2-响应式--框架底层采用 defineProperty这个api 监听对象属性变化
                缺点：新增的属性不能监听，
                    不能监听数组的方法（通过重写数组的方法来监听数组改变）
            vue3-响应式-框架底层采用采用proxy 这个api 监听对象属性变化

        
        */


        // vue2-响应式--框架底层采用 defineProperty这个api 监听对象属性变化

        /* 
        
          给对象定义一个属性
          Object.defineProperty(目标对象，属性名，配置对象)
          给目标对象定义属性-或者监听目标对象的属性 
           配置通过set get 监听 对象属性的 设置和获取
        */
        let obj = { a: 1 };


        // obj 添加了b属性
        // Object.defineProperty(obj, 'b', {
        //     value: 100,// b属性的初始值是100
        //     writable: true,//b属性是否可以被修改
        //     enumerable: false//是否能被遍历 for in
        // })

        // console.log(obj.b);

        // obj.b = 1;
        // console.log(obj.b);

        // for (var key in obj) {
        //     console.log(key);
        // }


        // setter 监听对象属性被设置-修改
        // getter 监听对象属性被 获取
        Object.defineProperty(obj, 'a', {
            get() {
                //监听到 b属性被 获取
                console.log('get');

                // 返回的值 就是 获取的值
                return 'aa';
            },
            set(newValue) {
                //监听到 b属性被 修改
                console.log('set');
                console.log(newValue);// 设置的时候 传入的值
            }
        })
        console.log(obj.b);//获取属性

        obj.b = '22'//修改属性

        console.log(obj.a);
        obj.a = '2000'




        let obj2 = {
            a: 1,
            b: 2
        }

        // 获取一个对象的所有的属性名 key -返回要给数组
        console.log(Object.keys(obj2));

        // 遍历对象所有的key
        Object.keys(obj2).forEach((key) => {
            let value = obj2[key]//属性值
            Object.defineProperty(obj2, key, {
                set(newValue) {
                    console.log('set');
                    // ----------调用 重新渲染dom
                    // 修改value的值
                    value = newValue
                }, get() {
                    console.log('get');
                    // 返回当前的value
                    return value
                }
            })
        })

        obj2.a = '1000';
        console.log(obj2.a);


        function observe(obj2) {
            Object.keys(obj2).forEach((key) => {
                let value = obj2[key]//属性值
                Object.defineProperty(obj2, key, {
                    set(newValue) {
                        console.log('set');
                        // ----------调用 重新渲染dom
                        // 修改value的值
                        value = newValue
                    }, get() {
                        console.log('get');
                        // 返回当前的value
                        return value
                    }
                })
            })
        }



        var arr = [9, 8, 7];
        observe(arr);

        arr[0] = 100
        arr.push(111)

        // 重写了数组的方法

        // 保存原来的push
        let push = Array.prototype.push;
        Array.prototype.push = function (...args) {
            // args 获取所有的实参

            console.log('修改dom ');

            // 调用push，传入当前的this，和参数 args
            push.apply(this, args)

        }







    </script>

</body>

</html>